package com.eapi.project.service.impl;

//import com.alibaba.spring.util.BeanUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.eapi.eapicommom.model.entity.User;
import com.eapi.project.common.ErrorCode;
import com.eapi.project.exception.BusinessException;
import com.eapi.project.model.dto.team.*;
import com.eapi.project.model.entity.Team;
import com.eapi.project.model.entity.UserTeam;
import com.eapi.project.model.enums.TeamStatusEnum;
import com.eapi.project.model.vo.TeamUserVO;
import com.eapi.project.model.vo.UserVO;
import com.eapi.project.service.TeamService;
import com.eapi.project.mapper.TeamMapper;
import com.eapi.project.service.UserService;
import com.eapi.project.service.UserTeamService;
import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.modelmapper.ModelMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.apache.commons.beanutils.BeanUtils;


import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.stream.Collectors;

/**
* @author 59966
* @description 针对表【team(队伍)】的数据库操作Service实现
* @createDate 2024-06-17 23:34:01
*/

// 事务,保证操作的原子性
@Transactional( rollbackFor = Exception.class)
@Service
public class TeamServiceImpl extends ServiceImpl<TeamMapper, Team>
    implements TeamService{

    @Resource
    private TeamMapper teamMapper;
    @Resource
    private UserService userService;
    private UserTeamService userTeamService;

    @Override
    public List<Team> searchTeamsByTags(List<String> tagNameList){
        if(CollectionUtils.isEmpty(tagNameList)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        QueryWrapper<Team> queryWrapper = new QueryWrapper<>();
        List<Team> teamList = teamMapper.selectList(queryWrapper);
        Gson gson = new Gson();
        return teamList.stream().filter(team -> {
            String tagsStr = team.getTags();
            if(StringUtils.isBlank(tagsStr)){
                return false;
            }
            Set<String> tagNamesSet = gson.fromJson(tagsStr, new TypeToken<Set<String>>(){}.getType());
            for(String tagName : tagNameList){
                if(!tagNamesSet.contains(tagName)){
                    return false;
                }
            }
            return true;
        }).collect(Collectors.toList());
    }

    @Override
    public Long addTeam( TeamAddRequest teamAddRequest, User loginUser){
        // 将 teamAddRequest 的值映射给team
        ModelMapper modelMapper = new ModelMapper();
        Team team = modelMapper.map(teamAddRequest, Team.class);
        // 2. 是否登录
        if(loginUser == null){
            throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR);
        }
        validateTeamCommon(team, loginUser, false);

        // 5. 插入队伍信息到队伍表
        Long userId = loginUser.getId();
        team.setUserId(userId);
        boolean result = save(team);
        if(!result){
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "创建队伍失败");
        }
        Long teamId = team.getId();

        // 6. 插入用户-队伍关系到关系表
        UserTeam userTeam = new UserTeam();
        userTeam.setUserId(userId);
        userTeam.setTeamId(teamId);
        userTeam.setJoinTime(new Date());
        boolean result2 = userTeamService.save(userTeam);
        if(!result2){
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "创建队伍失败");
        }

        return teamId;
    }

    @Override
    public List<TeamUserVO> listTeams(TeamQueryRequest teamQueryRequest, User loginUser) {
        Boolean isAdmin = loginUser.getUserRole().equals("admin") ? true : false;
        QueryWrapper<Team> queryWrapper = new QueryWrapper<>();
        if(teamQueryRequest != null){
            String teamName = teamQueryRequest.getTeamName();
            if(StringUtils.isNotBlank(teamName)){
                queryWrapper.like("teamName", teamName);
            }

            // 根据标签查询写了专门的方法！
            String tags = teamQueryRequest.getTags();
            if(StringUtils.isNotBlank(tags)){
                queryWrapper.like("tags", tags);
            }

            String description = teamQueryRequest.getDescription();
            if(StringUtils.isNotBlank(description)){
                queryWrapper.like("description", description);
            }
            //同时搜索符合条件的队伍名/描述
            String searchText = teamQueryRequest.getSearchText();
            if(StringUtils.isNotBlank(searchText)){
                queryWrapper.and(qw -> qw.like("teamName", searchText).or().like("description", searchText));
            }
            Integer status = teamQueryRequest.getStatus();
            queryWrapper.eq(status == null && !isAdmin,"status", 0);

            TeamStatusEnum teamStatusEnum = TeamStatusEnum.getEnumByValue(status);
            if(teamStatusEnum == null){
                teamStatusEnum = TeamStatusEnum.PUBLIC;
            }
            if(!isAdmin && TeamStatusEnum.SECRET.equals(teamStatusEnum)){
                throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
            }
            queryWrapper.eq("status", teamStatusEnum.getValue());

        }
        // 没有符合条件的team
        List<Team> teamList = list(queryWrapper);
        if(CollectionUtils.isEmpty(teamList)){
            return new ArrayList<>();
        }

        // 实现方式：
        // 1. 自己写SQL
        // ①搜索队长：select* from team t left join user u on t.userId = u.id
        // ②搜索队员：select* from team t
        // left join user u on t.userId = u.id left join user_team ut on t.id = ut.teamId

        //2. 关联查询
        // 创建人
        List<TeamUserVO> teamUserVOList = new ArrayList<>();
        for(Team team : teamList){
            Long userId = team.getUserId();
            if(userId == null){
                continue;
            }
            // 给user和teamuser脱敏
            ModelMapper modelMapper = new ModelMapper();
            User user = userService.getById(userId);
            if(user == null) {
                continue;
            }
            UserVO userVO = modelMapper.map(user, UserVO.class);
            TeamUserVO teamUserVO = modelMapper.map(team, TeamUserVO.class);
            teamUserVO.setCreateUser(userVO);
            teamUserVOList.add(teamUserVO);
        }
        return teamUserVOList;
    }

    @Override
    public boolean updateTeam(TeamUpdateRequest teamUpdateRequest, User loginUser) {
        if(teamUpdateRequest == null){
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        Long id = teamUpdateRequest.getId();
        if(id == null || id <= 0){
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        Team oldTeam = getTeamById(id);
        if(!oldTeam.getUserId().equals(loginUser.getId())){
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "无修改权限");
        }

        ModelMapper modelMapper = new ModelMapper();
        Team updateTeam = modelMapper.map(teamUpdateRequest, Team.class);
        validateTeamCommon(updateTeam, loginUser, true);

        return this.updateById(updateTeam);
    }

    @Override
    public Boolean joinTeam(TeamJoinRequest teamJoinRequest, User loginUser) {
        if(teamJoinRequest == null){
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        Long teamId = teamJoinRequest.getTeamId();
        Team team = getTeamById(teamId);

        Integer status = team.getStatus();
        TeamStatusEnum teamStatusEnum = TeamStatusEnum.getEnumByValue(status);
        if(TeamStatusEnum.PRIVATE.equals(teamStatusEnum)){
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "私有队伍不可加入");
        }
        String teamPassword = teamJoinRequest.getTeamPassword();
        if(TeamStatusEnum.SECRET.equals(teamStatusEnum) && !team.getTeamPassword().equals(teamPassword)){
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "密码错误");
        }

        QueryWrapper<Team> userTeamQueryWrapper = new QueryWrapper<>();
        // 判断队伍是否已满
        userTeamQueryWrapper.eq("teamId", teamId);
        long count = this.count(userTeamQueryWrapper);
        if(count >= team.getMaxMum()){
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "队伍已满");
        }
        //判断是否重复加入队伍
        Long userId = loginUser.getId();
        userTeamQueryWrapper.eq("userId", userId);
        List<Team> teamList = this.list(userTeamQueryWrapper);
        if(!teamList.isEmpty()){
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "已加入过该队伍");
        }

        // 更新用户-队伍表
        UserTeam userTeam = new UserTeam();
        userTeam.setUserId(userId);
        userTeam.setTeamId(teamId);
        userTeam.setJoinTime(new Date());
        return userTeamService.save(userTeam);
    }

    @Override
    public Boolean quitTeam(TeamQuitRequest teamQuitRequest, User loginUser) {
        if(teamQuitRequest == null){
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        Long teamId = teamQuitRequest.getTeamId();
        Team team = getTeamById(teamId);

        // 我是否加入了该队伍
        long userId = loginUser.getId();
        QueryWrapper<UserTeam> userTeamQueryWrapper = new QueryWrapper<>();
        userTeamQueryWrapper.eq("userId", userId).eq("teamId", teamId);
        long count = userTeamService.count(userTeamQueryWrapper);
        if(count == 0){
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "未加入队伍");
        }
        //队长不能退出队伍
        if(team.getUserId().equals(userId)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "队伍队长不能退出队伍");
        }

        return userTeamService.remove(userTeamQueryWrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteTeam(Long teamId, User loginUser) {
        Team team = getTeamById(teamId);
        // 校验队长权限
        long userId = loginUser.getId();
        if(!team.getUserId().equals(userId)){
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "无删除权限");
        }
        // 删除队伍-用户表的关联信息
        QueryWrapper<UserTeam> userTeamQuery = new QueryWrapper<>();
        userTeamQuery.eq("teamId", teamId);
        userTeamService.remove(userTeamQuery);

        // 更新队伍表
        return this.removeById(teamId);
    }

    private Team getTeamById(Long teamId) {
        if(teamId == null || teamId <= 0){
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        Team team = this.getById(teamId);
        if(team == null){
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "队伍不存在");
        }
        return team;
    }

    private void validateTeamCommon(Team team, User loginUser, boolean isUpdating) {
        // 校验队伍基本信息
        if (team == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        if (StringUtils.isNotBlank(team.getTeamName()) && team.getTeamName().length() > 20) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "队伍名称不符合要求");
        }
        if (StringUtils.isNotBlank(team.getDescription()) && team.getDescription().length() > 512) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "队伍描述不符合要求");
        }
        TeamStatusEnum teamStatusEnum = TeamStatusEnum.getEnumByValue(Optional.ofNullable(team.getStatus()).orElse(0));
        if (teamStatusEnum == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "队伍状态不符合要求");
        }
        String teamPassword = team.getTeamPassword();
        if (TeamStatusEnum.SECRET.equals(teamStatusEnum)) {   // 如果队伍为加密状态
            if (StringUtils.isBlank(teamPassword) || teamPassword.length() > 32) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "队伍密码不符合要求");
            }
        }

        // 更新操作不需要检查用户创建队伍的数量限制
        if (!isUpdating) {
            Long userId = loginUser.getId();
            QueryWrapper<Team> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("userId", userId);
            if (count(queryWrapper) >= 5) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户最多创建5个队伍");
            }

            int maxMum = Optional.ofNullable(team.getMaxMum()).orElse(0);
            if (maxMum > 50 || maxMum < 1) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "队伍人数不符合要求");
            }
        }
    }

}




